package SplineEngine
{
	import TabbedLesson.TabbedLessonModel;
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.filesystem.File;
	import flash.filesystem.FileMode;
	import flash.filesystem.FileStream;
	import flash.net.URLLoader;
	import flash.net.URLRequest;
	
	import mx.controls.Alert;
	
	import util.Observable;

	public class SplineEngineModel extends Observable
	{
		//private var homePage_view:HomePageView;
		//private var homePage_controller:HomePageController;
		private var container_sprite:Sprite;
		private var nativeContainer_object:Object;
		
		private var moduleRegistryPath_string:String;
		private var splineWorkspacePath_string:String;
		
		private var openedSplineModule_object:Object;// = new Object;
		private var moduleNames_array:Array= new Array;
		private var modulePaths_array:Array= new Array;
		private var moduleDiscription_array:Array = new Array;
		private var currentModuleIndex_int:int;
		
		public function SplineEngineModel(container:Sprite, stage:Object)
		{
			super();
			this.container_sprite=container;
			this.nativeContainer_object=stage;
			this.moduleRegistryPath_string= this.nativeContainer_object.getSplineSetingsDirectoryPath().toString();
			this.splineWorkspacePath_string=this.nativeContainer_object.getSplineWorkspaceDirectoryPath().toString();
			
//			this.homePage_controller= new HomePageController(this);
//			this.homePage_view= new HomePageView(this,this.homePage_controller,this.container_sprite);
//			this.homePage_controller.setView(this.homePage_view);
//			this.addObserver(this.homePage_view);
			
			this.loadModuleRegistry();
			//this.nativeContainer_object.setTimerControl();
		}
		
		
		//----------------------File handling functions-------------------------------------------------------//
		private function loadModuleRegistry():void
		{
			var moduleRegistry_file:File=new File(this.moduleRegistryPath_string+"/ModuleRegistry.xml");
			var selectedModuleIndex:int=0;
			
			if(!moduleRegistry_file.exists)
			{
				trace("ModuleRegistry.xml is absent ");
				var moduleRegistry_xml:XML = new XML(<Registry>
												</Registry>);
				this.writeXmlFile(moduleRegistry_file,moduleRegistry_xml);
				trace("ModuleRegistry.xml written");

			}
			else
			{
				trace("ModuleRegistry.xml exists ");
				this.loadFile(moduleRegistry_file);
			}
			
			this.sendDataModel(selectedModuleIndex);
		}
		
		private function sendDataModel(selectedModuleIndex:int):void
		{
			var infoObj_object:Object=new Object;
			infoObj_object.message = "refreshModuleListDataModel";
			infoObj_object.moduleNames_array = this.moduleNames_array;
			infoObj_object.moduleDiscription_array = this.moduleDiscription_array;
			infoObj_object.modulePaths_array = this.modulePaths_array;
			infoObj_object.selectedModuleIndex = selectedModuleIndex;
			trace("sending module list datamodel to view");
			this.sendNotificationToObservers(infoObj_object);
			
		}
		
		private function dataModelChanged(selectedModuleIndex:int):void
		{
			this.sendDataModel(selectedModuleIndex);
			this.updateModuleRegistry();
		}
		
		
		private function updateModuleRegistry():void
		{
			var moduleRegistry_file:File=new File(this.moduleRegistryPath_string+"/ModuleRegistry.xml");
			var moduleRegistry_xml:XML = new XML(<Registry>
												</Registry>);
			//moduleRegistry_xml =<Registry>
			//					</Registry>;
			//var xmlNode:XML=new XML(<Module></Module>);
			trace(this.moduleNames_array);
			//var xmlNode:XMLNode= new XMLNode(1,"Module");
			for(var i:int=0; i<this.moduleNames_array.length; i++)
			{
				/*xmlNode.attributes.name = this.moduleNames_array[i];
				trace("this.moduleNames_array[i]="+this.moduleNames_array[i]+"  i="+i);
				xmlNode.attributes.path = this.modulePaths_array[i];
				xmlNode.attributes.discription = this.moduleDiscription_array[i];*/
				var xmlNode:XML=new XML(<Module></Module>);
				xmlNode.@name = this.moduleNames_array[i];
				trace("this.moduleNames_array[i]="+this.moduleNames_array[i]+"  i="+i);
				xmlNode.@path = this.modulePaths_array[i];
				xmlNode.@discription = this.moduleDiscription_array[i];
				moduleRegistry_xml.appendChild(xmlNode);
			}
			
			this.writeXmlFile(moduleRegistry_file,moduleRegistry_xml);
				
		}
		
		private function writeXmlFile(file:File, xml:XML):void
		{
			var fileStream:FileStream = new FileStream;
			fileStream.open(file, FileMode.WRITE);
			fileStream.writeUTFBytes(xml.toXMLString());
			fileStream.close();
			trace(file.nativePath.toString());
		}
		
		private function loadFile(moduleRegistry_file:File):void
		{
			var urlLoader:URLLoader= new URLLoader;
			var urlRequest:URLRequest = new URLRequest(moduleRegistry_file.nativePath.toString());
			urlLoader.load(urlRequest);
			trace("Going to load module registry!!!");
			urlLoader.addEventListener(Event.COMPLETE,this.fileLoadingComplete);
			
		}
		
		private function fileLoadingComplete(event:Event):void
		{
			var moduleRegistry_xml:XML=new XML(event.target.data);
			var index:int=0;
			var selectedModuleIndex:int=0;
			for each(var node:XML in moduleRegistry_xml.Module)
			{
				this.moduleNames_array[index] = node.@name.toString();
				this.moduleDiscription_array[index] = node.@discription.toString();
				this.modulePaths_array[index] = node.@path.toString();
				index++;
			}
			
			trace("ModuleRegistry.xml loaded in local arrays" + this.moduleNames_array);
			this.sendDataModel(selectedModuleIndex);
		}
		//----------------------------------------------------------------------------------------//
		
		//------------------------------------------------------------creating new module----------------------------------------//
		private function checkModuleExistance(infoObj_object:Object):void
		{
			for each(var name:String in this.moduleNames_array)
			{
				if(infoObj_object.name.toString() == name)
				{
					var infoObject2_object:Object=new Object;
					infoObject2_object.message="Alert";
					infoObject2_object.type="Error";
					infoObject2_object.info="Error : A module of the same name already exists in the workspace, use another name";
					this.sendNotificationToObservers(infoObject2_object);
					return;
				}
			}
			
			this.createNewModule(infoObj_object);
		}
		
		private function createNewModule(infoObj_object:Object):void
		{
			trace("this.moduleNames_array before = "+this.moduleNames_array);
			this.moduleNames_array.push(infoObj_object.name.toString());
			trace("this.moduleNames_array before = "+this.moduleNames_array);
			trace ("######this.moduleDiscription_array before :" + this.moduleDiscription_array);
			this.moduleDiscription_array.push(infoObj_object.discription.toString());
			trace ("######this.moduleDiscription_array after :" + this.moduleDiscription_array);
			
			var newModule_file:File=new File(this.splineWorkspacePath_string+"/"+infoObj_object.name.toString());
			newModule_file.createDirectory();
			this.modulePaths_array.push(newModule_file.nativePath.toString());
			
			var newModuleXML_file:File = new File(newModule_file.nativePath.toString()+"/"+infoObj_object.name.toString()+".xml");
			var newModuleXML_xml:XML = new XML(<Module></Module>);
			this.writeXmlFile(newModuleXML_file, newModuleXML_xml);
			trace(infoObj_object.name.toString()+".xml made");
			
			var newModuleSpline_file:File = new File(newModule_file.nativePath.toString()+"/"+infoObj_object.name.toString()+".spm");
			var fileStream:FileStream=new FileStream;
			fileStream.open(newModuleSpline_file, FileMode.WRITE);
			fileStream.writeUTFBytes(infoObj_object.name.toString());
			fileStream.close();
			this.dataModelChanged(this.moduleNames_array.length - 1);
			//
		}
		//-----------------------------------------------------------------------------------------------------------------------------------------------------//
		
		//---------------------------------------opening existing module---------------------------------------------------------------------------------//
		/*private function checkOpenModules(infoObj_object:Object):void
		{
			var openedModule_array:Array = this.nativeContainer_object.openedTabs_array;
			for each(var tab:Object in openedModule_array)
			{
				if(infoObj_object.moduleName.toString() == tab.title)
				{
					return;
				}
			}
			
			this.openModule(infoObj_object);
		}*/
		
		private function openModule(infoObj_object:Object):void
		{
			var index:int=infoObj_object.selectedModuleIndex;
			var modulePath_string:String = this.modulePaths_array[index];
			//var homePageObject:Object=new Object;
			//homePageObject=infoObj_object.homePageObject;
			//var splineModule:SplineModule = new SplineModule(this.moduleNames_array[index], modulePath_string,infoObj_object, this);
			this.openedSplineModule_object = new SplineModule(this.moduleNames_array[index], modulePath_string, this);
			//this.sendNotificationToObservers(splineModule.openModule());
		}
		
		//----------------------------------------------------------------------------------------------------------------------------------------------------//
		
		//------------------------------------------------- delete modules--------------------------------------------------------------------//
		private function deleteSelectedModule(infoObj_object:Object):void
		{
			var index:int = infoObj_object.selectedModuleIndex;
			if(infoObj_object.completeRemoval)
			{
				var file:File=new File(this.modulePaths_array[index]);
				file.moveToTrash();
			}
			this.moduleNames_array.splice(index,1);
			this.moduleDiscription_array.splice(index,1);
			this.modulePaths_array.splice(index,1);
			
			var selectedModuleIndex:int = 0;
			this.dataModelChanged(selectedModuleIndex);
						
		}
		//--------------------------------------------------------------------------------------------------------------------------------------------//
		
		//-----------------------------------------------editModuleMetadata----------------------------------------------------------------------------------//
		private function editSelectedModuleMetadata(infoObj_object:Object):void
		{
			var index:int=infoObj_object.selectedModuleIndex;
			
			this.moduleNames_array[index]=infoObj_object.name.toString();
			this.moduleDiscription_array[index]=infoObj_object.discription.toString();
			
			this.dataModelChanged(index);
		}
		//------------------------------------------------------------------------------------------------------------------------------------------------//
		
		//---------------------------------------------------------create new lesson--------------------------------------------------------------//
		private function createLessonInSelectedModule(infoObj_object:Object):void
		{
			if(this.openedSplineModule_object!=null)
			{
				var index:int=infoObj_object.selectedModuleIndex;
				var modulePath_string:String = this.modulePaths_array[index];
				trace("creating a new instance of spline mod class to access the module named : "+this.moduleNames_array[index]+"  located at : "+modulePath_string);
				//var splineModule:SplineModule = new SplineModule(this.moduleNames_array[index], modulePath_string,infoObj_object,this);
				this.openedSplineModule_object.interpretUserMessage(infoObj_object);
				//splineModule.loadModule();
				trace ("sending the infoObj to crreate the new lesson named : "+ infoObj_object.name.toString());
				//this.sendNotificationToObservers(splineModule.createNewLesson(infoObj_object));
			}
			
		}
		//---------------------------------------------------------------------------------------------------------------------------------------//
		
		//-------------------------------------------------delete lesson----------------------------------------------------------------------------//
		private function deleteSelectedLesson(infoObj_object:Object):void
		{
			var index:int=infoObj_object.selectedModuleIndex;
			var modulePath_string:String = this.modulePaths_array[index];
			//var splineModule:SplineModule = new SplineModule(this.moduleNames_array[index], modulePath_string,infoObj_object,this);
			this.openedSplineModule_object.interpretUserMessage(infoObj_object);
			//this.sendNotificationToObservers(splineModule.removeLesson(infoObj_object));
		}
		//------------------------------------------------------------------------------------------------------------------------------------------//
		
		//---------------------------------------------------edit Lesson Metadata ------------------------------------------------------------------//
		private function editSelectedLessonMetadata(infoObj_object:Object):void
		{
			var index:int=infoObj_object.selectedModuleIndex;
			var modulePath_string:String = this.modulePaths_array[index];
			//var splineModule:SplineModule = new SplineModule(this.moduleNames_array[index], modulePath_string,infoObj_object,this);
			this.openedSplineModule_object.interpretUserMessage(infoObj_object);
			//this.sendNotificationToObservers(splineModule.editLessonMetadata(infoObj_object));
		}
		//------------------------------------------------------------------------------------------------------------------------------------------//
		
		//---------------------------------------------------open Selected Lesson--------------------------------------------------------------------//
		private function openSelectedLessonInNewTab(infoObj_object:Object):void
		{
			if(this.isLessonAlreadyOpened(infoObj_object))
			{
				return;
			}
			var infoPacket_object:Object = new Object;
			infoPacket_object.lessonName = infoObj_object.selectedLessonName.toString();
			infoPacket_object.lessonPath = this.modulePaths_array[infoObj_object.selectedModuleIndex]+"/"+infoObj_object.selectedLessonName.toString();
			infoPacket_object.openInNewWindow = infoObj_object.openInNewWindow;
			var newTabbedLesson:TabbedLessonModel = new TabbedLessonModel(infoPacket_object,this.nativeContainer_object,this.container_sprite);
		}
		
		private function isLessonAlreadyOpened(infoObj_object:Object):Boolean
		{
			var openedLessonsArray:Array = this.nativeContainer_object.getOpenedLessonsArray();
			for each(var lesson:Object in openedLessonsArray)
			{
				if(lesson.title.toString()=="SPLINE -----> "+infoObj_object.selectedLessonName.toString() || lesson.title.toString()==infoObj_object.selectedLessonName.toString())
				{
					 Alert.show("Selected Lesson already opened");
					 return true;
				}
				
			}
			
			return false;
		}
		//--------------------------------------------------------------------------------------------------------------------------------------------//
		
		//-----------------------------------------------information exchange functions ----------------------------------------------------------------------------------//
		
		public function tabTimerExists():Boolean
		{
			return false;
		}
		
		public function closeTab():void
		{
			var infoObj_object:Object = new Object;
			infoObj_object.message = "tabRemovalConfirmed";
			this.nativeContainer_object.incomingMessageGateway(infoObj_object);
		}
		
		public function requestEngineForUpdate():void
		{
			this.sendDataModel(0);
		}
		
				
		public function sendNotificationToObservers(infoObj_object:Object):void
		{
			trace("At the gate of SPLINE Engine :)")
			this.setChanged();
			this.notifyObservers(infoObj_object);
		}
		
		public function incomingMessageGateway(infoObj_object:Object):void
		{
			var message:String = infoObj_object.message.toString();
			
			switch(message)
			{
				case "createNewModule":
						trace("create new module");
						this.checkModuleExistance(infoObj_object);
						break;
				case "openModule":
						trace("Open Existing Module");
						this.openModule(infoObj_object);
						break;
				case "deleteModule":
						trace("delete module");
						this.deleteSelectedModule(infoObj_object);
						break;
				case "editModuleMetadata":
						trace("edit selected module");
						this.editSelectedModuleMetadata(infoObj_object);
						break;
				case "createNewLesson":
						trace("creating new lesson");
						this.createLessonInSelectedModule(infoObj_object);
						break;
				case "editLessonMetadata":
						trace("edit lesson metadata");
						this.editSelectedLessonMetadata(infoObj_object);
						break;
				case "deleteLesson":
						trace("deleting selected lesson");
						this.deleteSelectedLesson(infoObj_object);
						break;
				case "openLesson":
						trace("opening selected lesson");
						this.openSelectedLessonInNewTab(infoObj_object);
						break;
				default :
						trace("No matching service available");
			}
		}
		 
	}
}